/*
 * Copyright 2019-2025 the original author or authors.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.iiifi.kite.core.result;

import java.io.Serializable;
import java.util.Optional;

import org.springframework.lang.Nullable;

import com.iiifi.kite.core.exception.ServiceException;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

/**
 * 结果集封装
 *
 * @author kite@iiifi.com 花朝
 */
@Data
@ToString
@NoArgsConstructor
@ApiModel(description = "数据返回模型")
public class Result<T> implements Serializable {
    private static final long serialVersionUID = -1160662278280275915L;

    @ApiModelProperty(value = "code值", required = true)
    private int code;

    @ApiModelProperty(value = "消息", required = true)
    private String msg;

    @ApiModelProperty("返回对象")
    private T data;

    @ApiModelProperty("分页对象")
    private Pagination pagination;

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    private static class Pagination implements Serializable {

        private static final long serialVersionUID = -4348183755776153974L;
        @ApiModelProperty("总页数")
        private Long pageCount;

        @ApiModelProperty("总条数")
        private Long total;
    }

    private Result(IResultCode resultCode) {
        this(resultCode, resultCode.getMsg(), null);
    }

    private Result(IResultCode resultCode, String msg) {
        this(resultCode, msg, null);
    }

    private Result(IResultCode resultCode, T data) {
        this(resultCode, resultCode.getMsg(), data);
    }

    private Result(IResultCode resultCode, String msg, T data) {
        this.code = resultCode.getCode();
        this.msg = msg;
        this.data = data;
    }

    /**
     * 判断返回是否为成功
     *
     * @return 是否成功
     */
    public boolean isSuccess() {
        return isSuccess(this);
    }

    /**
     * 判断返回是否为成功
     *
     * @param result Result
     * @return 是否成功
     */
    public static boolean isSuccess(@Nullable Result<?> result) {
        return Optional.ofNullable(result)
                .map(r -> r.code)
                .map(code -> SystemCode.SUCCESS.code == code)
                .orElse(Boolean.FALSE);
    }

    /**
     * 判断返回是否为成功
     *
     * @param result Result
     * @return 是否成功
     */
    public static boolean isNotSuccess(@Nullable Result<?> result) {
        return !Result.isSuccess(result);
    }

    /**
     * 获取data
     *
     * @param result Result
     * @param <T> 泛型标记
     * @return 泛型对象
     */
    @Nullable
    public static <T> T getData(@Nullable Result<T> result) {
        return Optional.ofNullable(result)
                .filter(r -> r.isSuccess())
                .map(x -> x.data)
                .orElse(null);
    }

    /**
     * 返回成功
     *
     * @param <T> 泛型标记
     * @return Result
     */
    public static <T> Result<T> success() {
        return new Result<>(SystemCode.SUCCESS);
    }

    /**
     * 成功-携带数据
     *
     * @param data 数据
     * @param <T> 泛型标记
     * @return Result
     */
    public static <T> Result<T> success(@Nullable T data) {
        return new Result<>(SystemCode.SUCCESS, data);
    }

    /**
     * 分页查询成功-携带数据返回
     *
     * @param data 数据
     * @param <T> 泛型标记
     * @param pageCount 总页数
     * @param total 总条数
     * @return Result
     */
    public static <T> Result<T> success(@Nullable T data, Long pageCount, Long total) {
        Pagination pagination = new Pagination(pageCount, total);
        Result<T> result = new Result<>(SystemCode.SUCCESS, data);
        result.setPagination(pagination);
        return result;
    }

    /**
     * 根据状态返回成功或者失败
     *
     * @param status 状态
     * @param msg 异常msg
     * @param <T> 泛型标记
     * @return Result
     */
    public static <T> Result<T> status(boolean status, String msg) {
        return status ? Result.success() : Result.fail(msg);
    }

    /**
     * 根据状态返回成功或者失败
     *
     * @param status 状态
     * @param sCode 异常code码
     * @param <T> 泛型标记
     * @return Result
     */
    public static <T> Result<T> status(boolean status, IResultCode sCode) {
        return status ? Result.success() : Result.fail(sCode);
    }

    /**
     * 返回失败信息，用于 web
     *
     * @param msg 失败信息
     * @param <T> 泛型标记
     * @return {Result}
     */
    public static <T> Result<T> fail(String msg) {
        return new Result<>(SystemCode.FAILURE, msg);
    }

    /**
     * 返回失败信息
     *
     * @param rCode 异常枚举
     * @param <T> 泛型标记
     * @return {Result}
     */
    public static <T> Result<T> fail(IResultCode rCode) {
        return new Result<>(rCode);
    }

    /**
     * 返回失败信息
     *
     * @param rCode 异常枚举
     * @param msg 失败信息
     * @param <T> 泛型标记
     * @return {Result}
     */
    public static <T> Result<T> fail(IResultCode rCode, String msg) {
        return new Result<>(rCode, msg);
    }

    /**
     * 当 result 不成功时：直接抛出失败异常，返回传入的 result。
     *
     * @param result R
     */
    public static void throwOnFail(Result<?> result) {
        if (Result.isNotSuccess(result)) {
            throw new ServiceException(result);
        }
    }

    /**
     * 当 result 不成功时：直接抛出失败异常，返回传入的 rCode
     *
     * @param result R
     * @param rCode 异常枚举
     */
    public static void throwOnFail(Result<?> result, IResultCode rCode) {
        if (Result.isNotSuccess(result)) {
            throw new ServiceException(rCode);
        }
    }

    /**
     * 当 result 不成功时：直接抛出失败异常，返回传入的 rCode、message
     *
     * @param result R
     * @param rCode 异常枚举
     * @param msg 失败信息
     */
    public static void throwOnFail(Result<?> result, IResultCode rCode, String msg) {
        if (Result.isNotSuccess(result)) {
            throw new ServiceException(rCode, msg);
        }
    }

    /**
     * 当 status 不为 true 时：直接抛出失败异常 rCode
     *
     * @param status status
     * @param rCode 异常枚举
     */
    public static void throwOnFalse(boolean status, IResultCode rCode) {
        if (!status) {
            throw new ServiceException(rCode);
        }
    }

    /**
     * 当 status 不为 true 时：直接抛出失败异常 rCode、message
     *
     * @param status status
     * @param rCode 异常枚举
     * @param msg 失败信息
     */
    public static void throwOnFalse(boolean status, IResultCode rCode, String msg) {
        if (!status) {
            throw new ServiceException(rCode, msg);
        }
    }

    /**
     * 直接抛出失败异常，抛出 code 码
     *
     * @param rCode IResultCode
     */
    public static void throwFail(IResultCode rCode) {
        throw new ServiceException(rCode);
    }

    /**
     * 直接抛出失败异常，抛出 code 码
     *
     * @param rCode IResultCode
     * @param message 自定义消息
     */
    public static void throwFail(IResultCode rCode, String message) {
        throw new ServiceException(rCode, message);
    }
}
